/* Create linked list layout */

#include <algorithm>
#include <cmath>

#include <memchart/types.hpp>

#include "chart_box.hpp"
#include "vector2.hpp"

#include "memory_chart.hpp"

namespace memchart
{
	void MemoryChart::layout_list ()
	{
		int left = 0, minleft = 0, maxleft = 0;
		int top = 0, maxheight = 0;

		/* Maintain 4:3 aspect ratio */
		size_t hstep = 2 * std::sqrt(boxes.size() / 3.0) + 0.5;
		size_t cur = 0;

		make_boxes_unseen();
		box_iter v = list_head;
		bool rightwards = true;
		do
		{
			v->second.seen = true;

			/* Record widget coordinates */
			if (rightwards)
			{
				v->second.position = vector2(left, top);
				left += v->second.widget->get_width() + hspacing;
			}
			else
			{
				v->second.position =
					vector2(left - v->second.widget->get_width(), top);
				left -= v->second.widget->get_width() + hspacing;
			}
			maxheight = std::max(maxheight, v->second.widget->get_height());

			/* Get next element */
			if (is_tree) /* Singly linked list */
				v = boxes.find(v->second.edges[0]);
			else
			{
				box_iter v2 = boxes.find(v->second.edges[0]);
				if (v2 == boxes.end() || v2->second.seen)
				{
					v2 = boxes.find(v->second.edges[1]);
					if (v2 != boxes.end() && v2->second.seen)
						v2 = boxes.end();
				}
				v = v2;
			}

			/* Check if the row has ended */
			if (v == boxes.end() || ++cur == hstep)
			{
				cur = 0;
				top += maxheight + vspacing;
				maxheight = 0;
				if (rightwards)
					maxleft = std::max(maxleft, left -= hspacing);
				else
					minleft = std::min(minleft, left += hspacing);
				rightwards = !rightwards;
			}
		}
		while (v != boxes.end());
		top -= vspacing;

		/* Position widgets */
		for (box_iter v = boxes.begin(); v != boxes.end(); ++v)
		{
			chart_box & box = v->second;
			move(*box.widget, box.position.x - minleft, box.position.y);
		}

		set_size_request(maxleft - minleft, top);
	}
}
